Skip to content

fix(codex): opt into update_plan so the plan card survives 0.152.0 - #961

Closed
kaizhou-lab wants to merge 2 commits into
mainfrom
fix/codex-update-plan-opt-in
Closed

fix(codex): opt into update_plan so the plan card survives 0.152.0#961
kaizhou-lab wants to merge 2 commits into
mainfrom
fix/codex-update-plan-opt-in

Conversation

@kaizhou-lab

Copy link
Copy Markdown
Contributor

codex 0.152.0 made the update_plan tool opt-in, so AionUi's plan card goes permanently empty on that release. This opts back in.

What changed upstream

UpdatePlanToolConfig lost its default = "default_true" and now defaults to false — openai/codex a9519cbc, "Make the update_plan tool opt-in" (#41744). The same commit flips the default under that key in the machine-generated codex-rs/core/config.schema.json:

         "enabled": {
-          "default": true,
+          "default": false,

The model is therefore never offered the tool, no plan notification is ever emitted, and the card stays empty with no error anywhere. Not theoretical: 0.152.0 is npm's current latest, and we do not pin the user's CLI, so anyone who updates codex loses plan rendering silently.

Measured, not inferred

The single live test against each binary through its own PATH shim:

codex live_codex_produces_a_plan
0.151.0 (currently verified) 2/2 pass
0.152.0 2/2 fail — no plan frame anywhere in the stream

With the override, 0.152.0 passes and the frame is back.

The shim was proven to take, and here that mattered more than usual. The installed codex on this machine is 0.148.0, where update_plan is still default-on — so a shim that silently failed would have produced a passing test against the wrong binary. A wrapper shim recorded every invocation:

INVOKED ver=codex-cli 0.152.0 argv=app-server -c shell_environment_policy.inherit=all
  -c shell_environment_policy.include_only=[] -c tools.update_plan.enabled=true

Full codex live suite with the fix: 11/11 against 0.152.0, 484s, 58 recorded invocations — all the candidate, all carrying the override.

The change

The override rides in the existing compatibility block (codex_shell_environment_policy_args), so it applies to both initial open and idle wake, and it is harmless on older releases which already defaulted it to true.

The two argv assertions were updated, not loosened — they still assert the full expected argv, which is exactly what lets them catch a dropped override later. cargo test -p aionui-session --lib codex_conn: 145/145. Clippy clean, fmt clean.

Blocks the codex bump

VERIFIED_CODEX_VERSION stays at 0.151.0 until this lands: gate B is red on 0.152.0 without it, and a constant may not claim a verification its own tree cannot reproduce. The bump will follow in a later nightly run once this is on main.

Source change — left for human review, no auto-merge.

zk added 2 commits September 2, 2026 02:29
codex 0.152.0 made the update_plan tool opt-in. UpdatePlanToolConfig lost its
default = "default_true" and now defaults to false (openai/codex a9519cbc,
"Make the update_plan tool opt-in" #41744 -- the same commit flips default: true
to default: false under that key in codex-rs/core/config.schema.json).

The model is therefore never offered the tool, no plan notification is emitted,
and AionUi's plan card stays permanently empty. This is not theoretical: 0.152.0
is npm's current latest, and we do not pin the user's CLI, so anyone who updates
codex loses plan rendering with no error anywhere.

Measured, not inferred. Running the single live test against each binary through
its own PATH shim:

  0.151.0  live_codex_produces_a_plan  2/2 pass
  0.152.0  live_codex_produces_a_plan  2/2 fail -- no `plan` frame in the stream

With the override, 0.152.0 passes and the frame is back. Proven with a wrapper
shim that records every invocation, because the installed codex on this machine
is 0.148.0 -- where update_plan is still default-on -- so a shim that failed to
take would have produced a passing test against the wrong binary:

  INVOKED ver=codex-cli 0.152.0 argv=app-server -c shell_environment_policy.inherit=all
    -c shell_environment_policy.include_only=[] -c tools.update_plan.enabled=true

Full codex live suite with the fix: 11/11 against 0.152.0, 484s, 58 recorded
invocations, all of them the candidate and all carrying the override.

The override rides in the existing compatibility block, so it applies to both
initial open and idle wake, and it is harmless on older releases which already
defaulted it to true.

The two argv assertions were updated rather than loosened -- they still assert
the full expected argv, which is what makes them able to catch a dropped
override.
codex_shell_environment_policy_args is pub and has a second consumer outside
this crate -- acp_launch_policy.rs:83 extends the codex-acp.js argv with it --
so widening the helper changed that path's argv as well and its assertion went
red in CI.

The override belongs there: it is the same codex binary and the same benefit, so
plan cards survive 0.152.0 on the ACP path as well as on the direct app-server
one.

Checked that this does not break older installs before widening the reach: every
codex on this machine accepts the key, 0.148.0 included. Starting each with
`app-server -c tools.update_plan.enabled=true` produces no unknown-key or
invalid-config error on 0.148.0, 0.151.0 or 0.152.0 -- the only output is the
expected JSONRPC EOF from the empty stdin the check feeds it. The key predates
the default flip; only its default changed.

The assertion was extended, not loosened.
@kaizhou-lab

Copy link
Copy Markdown
Contributor Author

Superseded by #976.

The approach here was wrong. This PR passed -c tools.update_plan.enabled=true when spawning the app-server, and codex --help is explicit that -c overrides "a configuration value that would otherwise be loaded from ~/.codex/config.toml" — so it silently overrides a user who turned the tool off deliberately.

It is also not the same kind of setting as the two overrides beside it: shell_environment_policy.inherit=all / include_only=[] are compatibility requirements the host must control, while update_plan is a preference upstream made opt-in on purpose.

And the stake is smaller than this PR's body claimed. What is lost is a live progress view, not correctness — the turn still runs and still answers. "The plan card stays permanently empty" was inaccurate too: ConversationPlanBar renders nothing at all when there are no entries, so the bar simply does not appear.

#976 emits a one-shot Info notice naming the setting and the file instead, and leaves the choice with the user.

@kaizhou-lab kaizhou-lab closed this Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant